// HSS.Forms.TextControl.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       TextControl.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace HSS.Forms
{

	/// <summary>
	/// Summary description for TextControl.
	/// </summary>
	[Designer(typeof(HSS.Forms.Design.TextControlDesigner))]
	public partial class TextControl : System.Windows.Forms.Control
	{
		#region Fields
		private bool focused;
		private bool editUpdating;
		private bool displayUpdating;
		private Color textBackColor = Color.White;
		#endregion

		/// <summary>
		/// A customer Text Box that allow for string formatting.
		/// </summary>
		public TextControl()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();

			SetStyle(ControlStyles.UserPaint, true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.DoubleBuffer, true);
			SetStyle(ControlStyles.ResizeRedraw, true);
		}

		#region Properties
		/// <summary>
		/// The text to display in the TextControl
		/// </summary>
		[Description("The text to display in the control")]
		[Category("Appearance")]
		public override string Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				base.Text = value;
				this.txtDisplayTextBox.Text = value;
				this.txtEditTextBox.Text = value;
			}
		}


		/// <summary>
		/// Specify the Trimming Format
		/// </summary>
		[DefaultValue(StringTrimming.EllipsisWord)]
		[Description("The StringFormat Trimming Option to use.")]
		[Category("Appearance")]
		public StringTrimming TextTrimming
		{
			get { return _stringTrimming; }
			set
			{
				if (_stringTrimming != value)
				{
					_stringTrimming = value;
					this.txtDisplayTextBox.TextTrimming = value;
				}
				this.RecreateHandle();
			}
		} StringTrimming _stringTrimming = StringTrimming.EllipsisWord;

		/// <summary>
		/// Specify the Text Wrapping format
		/// </summary>
		[DefaultValue(StringFormatFlags.NoWrap)]
		[Description("The StringFormat Wrapping Option to use.")]
		[Category("Appearance")]
		public StringFormatFlags TextWrapping
		{
			get { return _textWrapping; }
			set
			{
				if (_textWrapping != value)
				{
					_textWrapping = value;
					this.txtDisplayTextBox.TextWrapping = value;
				}
				this.RecreateHandle();
			}
		} StringFormatFlags _textWrapping = StringFormatFlags.NoWrap;

		/// <summary>
		/// Gets or set the font of the text displayed by the control
		/// </summary>
		[Description("Gets or set the font of the text displayed by the control")]
		public override Font Font
		{
			get
			{
				return base.Font;
			}
			set
			{
				if (base.Font != value)
				{
					base.Font = value;
					this.Height = this.txtEditTextBox.Height;
				}
				this.RecreateHandle();
			}
		}


		/// <summary>
		/// The height of the control
		/// </summary>
		[DefaultValue(20)]
		[Category("LayOut")]
		[Description(" The height of the control")]
		public new int Height
		{
			get { return base.Height; }
			set
			{
				if (value > this.txtEditTextBox.Height)
					base.Height = this.txtEditTextBox.Height;
				else
				{
					base.Height = value;
					this.txtEditTextBox.Height = value;
				}
				this.txtDisplayTextBox.Height = base.Height;
			}
		}


		/// <summary>
		/// Gets or set the font of the text displayed by the control
		/// </summary>
		[DefaultValueAttribute(typeof(Color), "Color.Black")]
		public override Color ForeColor
		{
			get
			{
				return base.ForeColor;
			}
			set
			{
				if (base.ForeColor != value)
				{
					base.ForeColor = value;
				}
				this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
			}
		}


		/// <summary>
		/// Gets or set the font of the text displayed by the control
		/// </summary>
		[DefaultValueAttribute(typeof(Color), "Color.White")]
		public override Color BackColor
		{
			get
			{
				return textBackColor;
			}
			set
			{
				if (textBackColor != value)
				{
					textBackColor = value;
					if (Color.Transparent == textBackColor)
					{
						textBackColor = Color.White;
					}
				}
				base.BackColor = value;
				this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
			}
		}


		/// <summary>
		/// Indicates whether or not the edit control should have a border.
		/// </summary>
		[DefaultValue(2)]
		[Category("Appearance")]
		[Description("Indicates whether or not the edit control should have a border.")]
		public BorderStyle BorderStyle
		{
			get
			{
				return this.borderStyle;
			}
			set
			{
				if (this.borderStyle != value)
				{
					if (!Enum.IsDefined(typeof(BorderStyle), value))
					{
						throw new InvalidEnumArgumentException("value", (int)value, typeof(BorderStyle));
					}
					this.borderStyle = value;
					base.UpdateStyles();
					base.RecreateHandle();
				}
			}
		} BorderStyle borderStyle = BorderStyle.Fixed3D;

		/// <summary>
		/// Indicates whether or not the control contents can be modified.
		/// </summary>
		[DefaultValue(false)]
		[Category("Behavior")]
		[Description("Indicates whether or not the control contents can be modified.")]
		public bool ReadOnly
		{
			get { return _readOnly; }
			set
			{
				_readOnly = value;
				this.txtDisplayTextBox.ReadOnly = value;
				this.txtEditTextBox.ReadOnly = value;
			}
		} bool _readOnly = false;

		#endregion

		#region Event Handlers
		/// <summary>
		/// OnPaint
		/// </summary>
		/// <param name="e">PaintEventArgs</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			if (focused)
			{
				ShowEdit();
			}
			else
			{
				ShowDisplay();
			}
		}
		private void TextControl_SizeChanged(object sender, EventArgs e)
		{
			if (focused)
			{
				ShowEdit();
			}
			else
			{
				ShowDisplay();
			}
		}
		private void TextDisplay_Enter(object sender, EventArgs e)
		{
			focused = true;
			this.ShowEdit();
		}
		private void TextControl_Leave(object sender, EventArgs e)
		{
			focused = false;
			this.ShowDisplay();
		}
		private void txtEditTextBox_TextChanged(object sender, System.EventArgs e)
		{
			if (base.Text != this.txtEditTextBox.Text)
			{
				base.Text = this.txtEditTextBox.Text;
			}
		}
		#endregion

		#region Methods
		private void ShowEdit()
		{
			if (editUpdating)
				return;

			editUpdating = true;

			try
			{

				this.txtDisplayTextBox.Location = new Point(-20000, -20000);
				this.txtEditTextBox.Location = new Point(0, 0);

				this.txtEditTextBox.Size = new Size(this.Width - 1, this.Height);

				if (this.txtEditTextBox.BackColor != textBackColor)
					this.txtEditTextBox.BackColor = textBackColor;

				if (this.txtEditTextBox.ForeColor != this.ForeColor)
					this.txtEditTextBox.ForeColor = this.ForeColor;

				if (this.txtEditTextBox.BorderStyle != this.BorderStyle)
					this.txtEditTextBox.BorderStyle = this.BorderStyle;

				this.txtEditTextBox.BringToFront();
				this.txtEditTextBox.Focus();
				this.txtEditTextBox.Text = this.Text;
				this.txtEditTextBox.Update();

			}
			finally
			{
				editUpdating = false;
			}
		}
		private void ShowDisplay()
		{
			if (displayUpdating)
				return;

			displayUpdating = true;

			try
			{
				this.txtEditTextBox.Location = new Point(-20000, -20000);
				this.txtDisplayTextBox.Location = new Point(0, 0);
				this.txtDisplayTextBox.Size = new Size(this.Width - 1, this.Height);
				this.txtDisplayTextBox.BackColor = textBackColor;
				this.txtDisplayTextBox.ForeColor = this.ForeColor;
				this.txtDisplayTextBox.BorderStyle = this.BorderStyle;
				this.txtDisplayTextBox.BringToFront();
				this.txtDisplayTextBox.Text = this.Text;
				this.txtDisplayTextBox.Update();
			}
			finally
			{
				displayUpdating = false;
			}
		}
		#endregion



	}
}